// ============================================================================

//  blue hell
//
//  Copyright (C) 2002 by Jan Punter
//
//  Syntax definition for Nordlers


// ============================================================================

// LEX


L  [A-Za-z_@]
D  [0-9]
H  [0-9A-Fa-f]

{D}+                                Return( _INT  ); //            **1
{D}+((\.|\,){D}+)?([Ee][+-]?{D}+)?  Return( _INT  ); // Scaled INT **1 **2
(0[Xx])|\${H}*                      Return( _INT  ); //            **1 **3
[Cc][Oo][Nn][Ss][Tt]                Return( _CONST); // CONST
[Ll][Oo][Oo][Pp]                    Return( _LOOP ); // LOOP
[Ii][Nn][Cc][Ll][Uu][Dd][Ee]        Return( _INCL ); // INCLUDE    **4
"=="                                Return( _EQ   ); // ==  equal
"<>"                                Return( _NEQ  ); // <>  unequal
"!="                                Return( _NEQ  ); // !=  unequal
"<"                                 Return( _LT   ); // <   less than
"<="                                Return( _LE   ); // <=  less than or equal
">="                                Return( _GE   ); // >=  greater than oe equal
">"                                 Return( _GT   ); // >   greater than
"+"                                 Return( _PLUS ); // +   unary or binary plus
"-"                                 Return( _MINUS); // -   umary or binary minus
"*"                                 Return( _MULT ); // *   multiplication
[Dd][Ii][Vv]                        Return( _DIV  ); // DIV division
"/"                                 Return( _DIV  ); // /   division
[Mm][Oo][Dd]                        Return( _MOD  ); // MOD modulo operator
"%"                                 Return( _MOD  ); // %   modulo operator
[Nn][Oo][Tt]                        Return( _NOT  ); // NOT not    operator
"!"                                 Return( _NOT  ); // !   not    operator
[Oo][Rr]                            Return( _OR   ); // OR  or     operator
"|"                                 Return( _OR   ); // |   or     operator
[Xx][Oo][Rr]                        Return( _XOR  ); // XOR xor    operator
"^"                                 Return( _XOR  ); // ^   xor    operator
[Aa][Nn][Dd]                        Return( _AND  ); // AND and    operator
"&"                                 Return( _AND  ); // &   and    operator
{L}({L}|{D})*                       Return( _ID   ); // IDENTIFIER **5
\{                                  Returnc( '(');   //            **6
\}                                  Returnc( ')');   //            **6
"//".*                                               // COMMENT to end of line
\n                                                   // End of line
[\001-\011\013-\040]                                 // White space
.                              Returnc( yytext[ 1]); // literal chars ( like '('
                                                     //  '=' etc.), needed for
                                                     // Yacc

**1 : _ILLEGAL can also be returned when numeric conversion fails, e.g. on too
      many digits.

**2 : Scaled INT's are multiplied by 1000 before the value is sent to Yacc,
      these are meant to notate time in seconds in stead of the normal
      notation that assumes muili seconds.

**3 : Hexadecimal notation, the C like '0x' prefix can be used as well as the
      Pascal like '$' prefix.

**4 : INCLUDE is used to include files, file names must be an _ID, and they
      will be taken from the <application>\Include directory.

**5 : Apart from the identifiers defined by Lex (CONST, LOOP and INCLUDE)
      the following IDENTIFIER is predefined in the compiler itself :

      OUT - the primitive output procedure, all physical output must eventually
            use the OUT procedure. OUT can take an arbitrary number of input
            parameters, and OUT is the only predifined procedure in the system.

            The first parameter for OUT is assumed to be a device
            identification number, which can be 1 .. 65535 - do not use
            Device 0, as this will not result into usable output.

**6 : Curly braces '{' and '}' are translated into normal braces '(' and ')',
      so they can be intermingled.

// ============================================================================

YACC


/* terminal definitions */

%token <T_INT>             _INT      /* integer number */
%token <TId>               _ID       /* symbol         */
%token                     _CONST    /* constant       */
%token                     _LOOP     /* loop           */
%token                     _INCL     /* include        */
%token                     _ILLEGAL  /* illegal token  */
%token                     _EQ
%token                     _NEQ
%token                     _LT
%token                     _LE
%token                     _GE
%token                     _GT
%token                     _PLUS
%token                     _MINUS
%token                     _MULT
%token                     _DIV
%token                     _MOD
%token                     _NOT
%token                     _OR
%token                     _XOR
%token                     _AND

%%

nordler
  : definitions
  ;

definition_LIST
  : /* empty */
  | '(' definitions ')'
  ;

definitions
  : definitions definition
  | definition
  ;

definition
  : action ';'
  | procdef ';'
  | loopdef ';'
  | constdef ';'
  | include ';'
  | error ';'
  ;

action
  : expr _ID param_LIST
  ;

param_LIST
  : /* empty */
  | '(' params ')'
  ;

params
  : params ',' expr
  | expr
  ;

procdef
  : _ID id_LIST ';' definition_LIST
  ;

id_LIST
  : /* empty */
  | '(' ids ')'
  ;

ids
  : ids ',' _ID
  | _ID
  ;

loopdef
  : _LOOP '(' _ID ',' expr ',' expr expr_OPTION ')' ';' definition_LIST
              |       |        |    |
              |       |        |    +-- increment option, 1 if not present
              |       |        +------- loop end   expression, last value for
              |       |                            loop iterator
              |       +---------------- loop start expression, first value for
              |                                    loop iterator
              +------------------------ loop iterator
  ;

expr_OPTION
  : /* empty */
  | ',' expr
  ;

constdef
  : _CONST _ID '=' expr
  ;

include
  : _INCLUDE _ID
  ;

expr
  : simple_expr
  | simple_expr _EQ  simple_expr
  | simple_expr _NEQ simple_expr
  | simple_expr _LT  simple_expr
  | simple_expr _LE  simple_expr
  | simple_expr _GE  simple_expr
  | simple_expr _GT  simple_expr
  ;

simple_expr
  : term
  | _PLUS term
  | _MINUS term
  | simple_expr _PLUS  term
  | simple_expr _MINUS term
  | simple_expr _OR    term
  | simple_expr _XOR   term
  ;

term
  : factor
  | term _MULT factor
  | term _DIV  factor
  | term _MOD  factor
  | term _AND  factor
  ;

factor
  : _INT
  | _ID
  | '(' expr ')'
  | _NOT factor
  ;
